今天文章輕鬆一點,來介紹一個簡單的 ES6 新特性:Enhanced Object Literals。
平常我們用大括號 ({}
) 來建立物件的語法,就稱為物件實字 (Object Literals)。
以下例子是典型的物件實字語法:
var obj = {};
var player = {
name: "OneJar",
progress: 23,
sayHi: function(){
return "Hello";
},
language1: "JavaScript",
language2: "Java",
language3: "C"
};
物件實字的語法重點:
ES6 支援一些新的語法,讓物件實字能夠更簡潔、靈活。
時常會有這樣的情境:要使用已存在的變數名稱對物件屬性作初始化,而命名習性的關係,變數名稱可能和屬性名稱一模一樣。
好拗口,我們還是來看例子吧:
function getPlayerObj(name, progress){
return {
name: name,
progress: progress
};
}
console.log( getPlayerObj("OneJar", 23) ); // {name: "OneJar", progress: 23}
我想把變數 name
和 progress
作為物件屬性 name
和 progress
的初始值,變數名稱和屬性名稱碰巧一模一樣。
在 ES5 以前,必須把屬性名稱和進行賦值的變數名稱都標明清楚。
寫清楚並沒有不好,只是當這種情境越來越多,程式碼看起來可能稍嫌囉嗦。
對於這種「屬性名稱和進行賦值的變數名稱一模一樣」的情境,ES6 提供了更簡潔的語法:
function getPlayerObj(name, progress){
return {
name,
progress
};
}
console.log( getPlayerObj("OneJar", 23) ); // {name: "OneJar", progress: 23}
ES5 以前,物件函式的宣告方式就是使用 function
關鍵字進行函數的定義:
function getPlayerObj(name, progress){
return {
sayHi: function(){
return `Hi, I am ${name}`;
}
};
}
console.log( getPlayerObj("OneJar", 23).sayHi() ); // "Hi, I am OneJar"
ES6 支援更簡潔的寫法,省略了 function
關鍵字和冒號 :
:
function getPlayerObj(name, progress){
return {
sayHi(){
return `Hi, I am ${name}`;
}
};
}
console.log( getPlayerObj("OneJar", 23).sayHi() ); // "Hi, I am OneJar"
物件函式寫法除了用 function
關鍵字定義傳統函數,也可以用箭頭函數 (Arrow Functions) 的方式定義:
function getPlayerObj(name, progress){
return {
sayHi: () => {
return `Hi, I am ${name}`;
}
};
}
前面幾天的文章,我們談到傳統函數和箭頭函數 (Arrow Functions) 的差異,兩者的運作行為有很大不同。
那透過 ES6 簡寫語法所定義的物件函式,行為是傳統函數還是箭頭函數?
答案是傳統函數。
如何得知?
很簡單,只要一個簡單的測試。
例如箭頭函數不會為自己產生一個新的 arguments
物件,如果使用 arguments
發生錯誤,就代表是箭頭函數:
var player = {
sayHi: (name) => {
console.log(arguments); // ReferenceError: arguments is not defined
return `Hi, I am ${name}`;
}
};
console.log( player.sayHi("OneJar") );
若能正常取到屬於這個函數的 arguments
,就代表是傳統函數:
var player = {
sayHi(name){
console.log(arguments); // Arguments(1) ["OneJar"]
return `Hi, I am ${name}`;
}
};
console.log( player.sayHi("OneJar") ); // "Hi, I am OneJar"
ES5 以前的物件實字語法,無法透過運算去定義屬性名稱。
例如無法在程式執行過程,透過運算來動態決定下面 player
物件裡的屬性名稱要叫 language1
或是 lng1
:
var player = {
language1: "JavaScript",
language2: "Java",
language3: "C"
};
var player = {
lng1: "JavaScript",
lng2: "Java",
lng3: "C"
};
當然,你還是可以用以下的寫法去達到目的:
var prefix = "lng";
var i = 0;
var player = {};
player[prefix + (++i)] = "JavaScript";
player[prefix + (++i)] = "Java";
player[prefix + (++i)] = "C";
console.log(player); // {lng1: "JavaScript", lng2: "Java", lng3: "C"}
只是這種寫法就不是所謂的物件實字而已。
ES6 直接在物件實字的語法內增加可運算的特性,算是提供了另一種語法選擇:
var prefix = "lng";
var i = 0;
var player = {
[prefix + (++i)]: "JavaScript",
[prefix + (++i)]: "Java",
[prefix + (++i)]: "C"
};
console.log(player); // {lng1: "JavaScript", lng2: "Java", lng3: "C"}
ES6 提升了物件實字語法的簡潔性和靈活性,總共有 3 個部分的加強:
Enhanced Object Literal 是 ES6 中算滿簡單的新特性,唯一值得特別注意的是:透過 ES6 簡寫的物件函式,函數行為是傳統函數而非箭頭函數。
經過前面幾天的介紹,相信對箭頭函數和傳統函數的行為差異已經有一定的概念,能夠很輕鬆地理解為什麼 ES6 簡寫的物件函式是傳統函數,這也是為什麼把本篇主題接在箭頭函數之後才介紹。